package ar.com.ford.it.fullEconomics.persistence.dao;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Vector;
import oracle.toplink.expressions.Expression;
import oracle.toplink.expressions.ExpressionBuilder;
import oracle.toplink.queryframework.ReportQuery;
import oracle.toplink.queryframework.ReportQueryResult;
import oracle.toplink.sessions.Session;
import oracle.toplink.tools.sessionmanagement.SessionManager;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.persistence.PersistenceException;
import com.ford.it.persistence.PersistenceManager;
import com.ford.it.persistence.impl.toplink.ObjectId;
import com.ford.it.properties.PropertyGroup;
import com.ford.it.properties.PropertyManager;

public abstract class Dao {

    private static String PERSISTENCE_CONFIG = "/resources/persistence-config.xml";

    public String getSessionName() throws FileNotFoundException {
        PropertyManager pMgr = PropertyManager.getInstance();
        InputStream stream = Dao.class.getResourceAsStream(PERSISTENCE_CONFIG);
        
        pMgr.load(stream);
        PropertyGroup root = pMgr.getChildGroup("PersistenceConfig");
        String sessionName = null;
        if (root != null) {
            PropertyGroup pg = (PropertyGroup) root.getChildGroups().next();

            sessionName = pg.getString("toplinkSessionName");
            if (sessionName == null) {
                // Valor por defecto
                sessionName = pg.getName();
            }
        }
        return sessionName;
    }
    
	public Object getObjById(Object obj) throws PersistenceException {
		PersistenceManager pm = PersistenceUtil.getPersistenceManager();
		ObjectId objId = (ObjectId)pm.getObjectId(obj);
		return pm.getObjectById(objId);
	}
	
	
	public Object getObjForUpdate(Object objPk) throws PersistenceException {
		Object obj = getObjById(objPk);
		Object workingCopy = null;
		if (obj != null)
			workingCopy = PersistenceUtil.getTransaction().registerUpdate(obj);
		return workingCopy;
	}
    
    /**
     * Busca todos los registros cuyos campos especificados en "fields" tienen los valores
     * especificados en "values" 
     * 
     * @param obj
     * @param fields Contiene los nombres de los campos. Si es null se devuelven todos los registros
     * sin condiciones.
     * @param values Contiene los valores de los campos
     * @return Coleccion de objetos de la clase a la que pertenece "obj"
     * @throws PersistenceException
     */
    public Collection findAll(Object obj, String[] fields, Object[] values) throws PersistenceException {
        SessionManager manager = SessionManager.getManager();
        Session session = null;
        Collection res = null;
        ExpressionBuilder builder = new ExpressionBuilder();
        Expression exp = null;
        
        try {
            session = manager.getSession(this.getSessionName());
            if (fields == null) {
                res = session.readAllObjects(obj.getClass());
            } else {
                exp = builder.get(fields[0]).equal(values[0]);
                for (int i = 1; i < fields.length; i++) {
                    exp = exp.and(builder.get(fields[i]).equal(values[i]));
                }
                res = session.readAllObjects(obj.getClass(), exp);
            }
            return res;
        } catch (FileNotFoundException e) {
            
            e.printStackTrace();
            throw new PersistenceException(e);            
        }               
    }
    
    /**
     * Devuelve el maximo valor del campo "maxFieldName", que cumple con los valores "values"
     * de los campos "fields"
     * 
     * @param obj Instancia de la clase que mapea a la tabla de la cual se desea obtener el maximo
     * @param fields Campos que como condicion deben tener los valores indicados en "values". Si
     * es null entonces se toma el maximo del campo "maxFieldName" sin condiciones
     * @param values Valores de los campos indicados en "fields"
     * @param maxFieldName Campo para el cual se va a buscar el maximo
     * @return Maximo del campo "maxFieldName"
     * @throws PersistenceException
     */
    public Integer getMax(Object obj, String[] fields, Object[] values, String maxFieldName) throws PersistenceException {
        SessionManager manager = SessionManager.getManager();
        Session session = null;
        ReportQueryResult rqr = null;
        Integer res = null;
        Vector vec = null;
        ExpressionBuilder builder = new ExpressionBuilder();
        Expression exp = null;
        ReportQuery query = null;
        
        try {
            session = manager.getSession(this.getSessionName());
            query = new ReportQuery(builder);
            query.setReferenceClass(obj.getClass());
            query.addMaximum("max", builder.get(maxFieldName));
            if (fields != null) {
                exp = builder.get(fields[0]).equal(values[0]);
                for (int i = 1; i < fields.length; i++) {
                    exp = exp.and(builder.get(fields[i]).equal(values[i]));
                }
                query.setSelectionCriteria(exp);
            }
            vec = (Vector) session.executeQuery(query);
            
            // El resultado es unico
            rqr = (ReportQueryResult) vec.get(0);
            res = (Integer) rqr.get("max");
            return res == null ? 0 : res;
        } catch (FileNotFoundException e) {
            
            e.printStackTrace();
            throw new PersistenceException(e);            
        }
    }
    
}
